#include <iostream>
#include <time.h>
#include <ctype.h>
#include<sys/ioctl.h>
#include<termios.h>
#include <string>
#include<stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <vector>


using namespace std;

void file_put_content(string fileName,string fileData,const char *type){
        FILE *fp;
        fp=fopen(fileName.c_str(),type);
        if(!fp) {
            return throw new Exception("open file err! ");
        }
        fwrite(fileData.c_str(),fileData.size(),1,fp);
        fclose(fp);
}

void file_put_content(string fileName,string fileData){
    file_put_content( fileName, fileData,"wb");
}

vector<string>  filea( string fileName ,const char *type="r"){
        vector<string>  rt;
        FILE *fp;
        fp=fopen(fileName.c_str(),type);
        if(!fp)          throw new Exception("open file err! ");
        char s[1024];  
        while((fgets(s,1024,fp))!=NULL)  
         {  
            rt.push_back(s);
         }  
        
        fclose(fp);
        
        return rt;
}

vector<string> listdir(const char* path,const char *type=""){
         FILE *fp;
         vector<string> rt;
       DIR    *dir;
        struct    dirent    *ptr;
        dir = opendir(path); ///open the dir
        while((ptr = readdir(dir)) != NULL) ///read the list of this dir
        {
            char *p=strstr(ptr->d_name,type);
            if(strlen(type) == 0 ||  p!=NULL && strlen(p) == strlen(type)){
                rt.push_back(ptr->d_name);
            }
                //printf("d_type:%d d_name: %s\n", ptr->d_type,ptr->d_name); 
        }
        closedir(dir);
        return rt;
}

char *substr(char *str,int start,int len){
    if(len<0) len=strlen(str)-len;
    char *s=(char *) malloc(len+8);
    memset(s,0,len+8);  
    memcpy(s,(char *)str+start,len);
    return s;
}
long htoi(const char *s){
    long rt=0,n,m=strlen(s);
    for(int i=s[0]=='0' ? 2 : 0;i<m;i++) {
//        rt=rt*100+s[i];
        if(s[i]>='A'&&s[i]<='F')//十六进制还要判断他是不是在A-F或者a-f之间a=10。。
                n=s[i]-'A'+10;
        else if(s[i]>='a'&&s[i]<='f')
                n=s[i]-'a'+10;
        else n=s[i]-'0';
        rt=rt*16+n;
    }

    return rt;
}

template<typename typea>
void die(typea s,bool e=true) {
    cout <<s <<endl;
    if(e) exit(0);
}


string date(const char *format="%Y-%m-%d %H:%M:%S", int seconds=-1){
    string rt;
    time_t t;  
    struct tm *p;  
    if(!seconds) return rt;
    
    t=(int)seconds >0 ? seconds : time(NULL);  
    p=gmtime(&t);  
    char s[100];
    strftime(s, sizeof(s), format, p);
    
     rt=s;
    return rt;
}

string date(int time){
    return date("%Y-%m-%d %H:%M:%S",time);
}

char *sizeFormat(long n) {
        long size=n/2/1024;
        std::ostringstream   ostr;
        if(size>1024) ostr   <<size/1024<<"G";
        ostr    << size%1024 << "M" ;
        string rt=ostr.str();
        char *s=(char *) malloc(20);
        memset(s,0,20);  
        memcpy(s,rt.c_str(),20);
        return s;
}

std::string& trim(std::string &s)   
{  
    if (s.empty())   
    {  
        return s;  
    }  

    s.erase(0,s.find_first_not_of(" \n\r\t"));  
    s.erase(s.find_last_not_of(" \n\r\t") + 1);   
    return s;  
}  


void split(string& s, const char *delim,string *ret)  
{  
    int i=0;
    size_t last = 0;  
    size_t index=s.find_first_of(delim,last);  
    while (index!=std::string::npos)  
    {  
        ret[i++]=s.substr(last,index-last);  
        last=index+1;  
        index=s.find_first_of(delim,last);  
    }
    
    if (index-last>0)  
    {  
        ret[i++]=s.substr(last,index-last);  
    }  
}  


vector<string> split(string s, const char *delim=" \n\r\t")
{  
    int i=0;
//    string s=sp;
    size_t last = 0;  
    size_t index=s.find_first_of(delim,last);  
    vector<string> ret;
    while (index!=std::string::npos)  
    {  
        ret.push_back(s.substr(last,index-last));  
        last=index+1;  
        index=s.find_first_of(delim,last);  
    }
    
    if (index-last>0)  
    {  
        ret.push_back(s.substr(last,index-last));  
    }  
    
    return ret;
}  
vector<string> split(char *sp, const char *delim=" \n\r\t"){
    string s=sp;
    return split(s,delim);
}
//判断字符串是不是数字
bool isNumber(char*str,int i=-1){
    char *p=str;
    while (*p && i--) 
        if(!isdigit(*p++)) 
                return false;
    return true;
}

//包含中文的时候退格数量获取 
 template<typename typea>
 int strlenShow(typea *s){
       int i=0,j;
      typea *p=s;
      char c;
       while(c=*(p++)) {
          if(c<0){
           do{
                c=*p++;
            }while(c<0 && !(c <<1 &0x80));  
            p--;
            i+=2; continue;
          }
          i++;
      }   
      return i;
  }
 
 /**
  * 返回中文字符长度
  * s 字符串
  * dir 方向 true正向 false 逆向 
  */
 template<typename typea>
 int strlenChar(typea *s,bool dir=true){
       int i=0,j;
      typea *p=s;    if(dir==false) p+=strlen(s)-1;
      char c= (dir==true)? *p++: *p--;
       if(c<0){
          do{
              c=(dir==true)? *p++: *p--;
          }while(c<0 && !(c <<1 &0x80));  
//          dir && *p--;
          return  (dir ? p-s :s+strlen(s)-p)-1;
        }
      return 1;
  }

 /**
  * b 背景颜色 1~7   红色, 绿色,棕色,蓝色,紫色,青色,白色
  * c 字体颜色  
  * B 粗体
  * X 下划线
  * S 闪烁
  */
 void setColor(int b=0,int c=0,bool B=false,bool X=false,bool S=false){
         printf("\033[0m");
         if(B) printf("\033[1m");
         if(X) printf("\033[4m");
         if(S) printf("\033[5m");
         if(b) printf("\033[4%dm",b);
         if(c) printf("\033[3%dm",c);
 }
 const char* getColor(int b=0,int c=0,bool B=false,bool X=false,bool S=false){
        string str;
        char s[20];
         str= "\033[0m";
         if(B) str+="\033[1m";
         if(X) str+="\033[4m";
         if(S) str+="\033[5m";
         if(b) { sprintf(s,"\033[4%dm",b); str+=s;}
         if(c) { sprintf(s,"\033[3%dm",c); str+=s;}
         
         return str.c_str();
 }
 
int getWinsize(const char*type="col"){
        struct winsize info;
        ioctl(STDIN_FILENO,TIOCGWINSZ,&info);
//        printf("当前终端为%d行%d列\n",info.ws_row,info.ws_col);
        if(type=="col"){
            return info.ws_col;
        }else if(type=="row"){
            return info.ws_row;
        }else if(type=="x"){
            return info.ws_xpixel;
        }else if(type=="y"){
            return info.ws_ypixel;
        }else 
            return 0;
 }

 template<typename typeh>
 class HistoryArray{
    int index;
    int max;
    vector <typeh> historyData;
    public:
        HistoryArray(){
            this->max=100;
        }
        
        void push(typeh i) {
            if(historyData.size()>0 && i==historyData.back()) return;
            historyData.push_back(i);
            if(historyData.size() > this->max )       historyData.erase(historyData.begin());
            this->index=historyData.size()-1;
        }
        
        typeh  get(int i){
            int size =historyData.size()-1;
            this->index+=i;
            if(this->index<0) this->index=0;
            else if(this->index> size)  this->index = size;
            return historyData.at(this->index);
        }
};